/*
	Author - Pieman
	
	@TODO
		- Make formatting thingy.
		- Various performance tweaks.

	REVISIONS
	
	19-02-08 dodob
		- Update timestamps in search.x
			- hacky copy-and-pasting of function...
			- less intensive than conditional on each call?
		- Update timestamps in Messagecenter.

	18-02-08 dodob
		- Removed id field from timeZones table (getTimeZoneList changed)
		  (cleaner, no perf impact?)
		- Added 24-hour clock option.
		- Added hide timezone abbreviation option.
		- Added option to fix Shack server time (+3 min).
		- Re-organized control panel with above user options.
		- Hard coded pretty descriptions in the timeZones table;
		  gave up on pretty-formatting offset

	26-08-07
		- Updated control panel to reflect user changes.
		- Improved performance of script by using XPath, thanks ThomW!

	14-08-07
		- Initial Release.

*/
if (script_enabled('shacktimezone') == "true") 
{
	// grab start time of script
	var benchmarkTimer = null;
	var scriptStartTime = getTime();
	function getTime() { benchmarkTimer = new Date(); return benchmarkTimer.getTime(); }

	var timeZoneOffset;
	var timeZoneAbbr;
	var userSettingHideAbbr;
	var userSetting24Hr;
	var userSettingFixShackTime;
	var dateRegex = /(\|\s|)([\w]{3})\s([\d]{2}),\s([\d]{4})\s([\d]{1,2}):([\d]{2})([\w]{2})\s([\w]{3})/;
	var dateRegexSearch = /(\|\s|)([\d]{1,2})\s([\w]{3})\s([\d]{4})\s([\d]{2}):([\d]{2})/;
	var monthArray = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
	var timeZones = [
		{"offset":-12, "abbr":"Y", "desc":"(GMT -12:00) Eniwetok, Kwajalein"},
		{"offset":-11, "abbr":"X", "desc":"(GMT -11:00) Midway Island, Samoa"},
		{"offset":-10, "abbr":"HST", "desc":"(GMT -10:00) Hawaii"},
		{"offset":-9, "abbr":"AKST", "desc":"(GMT -9:00) Alaska"},
		{"offset":-8, "abbr":"PST", "desc":"(GMT -8:00) Pacific Time (US &amp; Canada)"},
		{"offset":-7, "abbr":"MST", "desc":"(GMT -7:00) Mountain Time (US &amp; Canada)"},
		{"offset":-6, "abbr":"CST", "desc":"(GMT -6:00) Central Time (US &amp; Canada), Mexico City"},
		{"offset":-5, "abbr":"EST", "desc":"(GMT -5:00) Eastern Time (US &amp; Canada)"},
		{"offset":-4, "abbr":"AST", "desc":"(GMT -4:00) Atlantic Time (Canada)"},
		{"offset":-3.5, "abbr":"NST", "desc":"(GMT -3:30) Newfoundland"},
		{"offset":-3, "abbr":"P", "desc":"(GMT -3:00) Brazil, Buenos Aires, Georgetown"},
		{"offset":-2, "abbr":"O", "desc":"(GMT -2:00) Mid-Atlantic"},
		{"offset":-1, "abbr":"N", "desc":"(GMT -1:00) Azores, Cape Verde Islands"},
		{"offset":0, "abbr":"GMT", "desc":"(GMT) Western Europe Time, Manchester"},
		{"offset":1, "abbr":"CET", "desc":"(GMT +1:00) CET(Central Europe Time), Brussels"},
		{"offset":2, "abbr":"EET", "desc":"(GMT +2:00) EET(Eastern Europe Time)"},
		{"offset":3, "abbr":"C", "desc":"(GMT +3:00) Baghdad, Moscow"},
		{"offset":3.5, "abbr":"IST", "desc":"(GMT +3:30) Tehran"},
		{"offset":4, "abbr":"D", "desc":"(GMT +4:00) Abu Dhabi, Tbilisi"},
		{"offset":4.5, "abbr":"AST", "desc":"(GMT +4:30) Kabul"},
		{"offset":5, "abbr":"WAST", "desc":"(GMT +5:00) Ekaterinburg, Islamabad"},
		{"offset":5.5, "abbr":"IST", "desc":"(GMT +5:30) Bombay, Calcutta"},
		{"offset":6, "abbr":"F", "desc":"(GMT +6:00) Almaty, Dhaka, Colombo"},
		{"offset":7, "abbr":"G", "desc":"(GMT +7:00) Bangkok, Hanoi, Jakarta"},
		{"offset":8, "abbr":"AWST", "desc":"(GMT +8:00) Beijing, Perth, Singapore"},
		{"offset":9, "abbr":"I", "desc":"(GMT +9:00) Tokyo, Seoul, Osaka, Sapporo, Yakutsk"},
		{"offset":9.5, "abbr":"ACST", "desc":"(GMT +9:30) Adelaide, Darwin"},
		{"offset":10, "abbr":"EAST", "desc":"(GMT +10:00) EAST(East Australian Standard)"},
		{"offset":11, "abbr":"L", "desc":"(GMT +11:00) Magadan, Solomon Islands"},
		{"offset":12, "abbr":"M", "desc":"(GMT +12:00) Auckland, Wellington"}
	];
	
	function factory() {
		/*
		if(window.location.pathname == '/settings/account.x') {
					return settingsFactory();
				}
		*/
        if (String(location.href).indexOf('frame_laryn') == -1){
            settingsFactory();
        }
		timeZoneOffset = GM_getValue("timeZoneOffset", 21600);
		timeZoneAbbr = GM_getValue("timeZoneAbbr", "GMT");
		userSettingHideAbbr = GM_getValue("userSettingHideAbbr", false);
		userSetting24Hr = GM_getValue("userSetting24Hr", false);
		userSettingFixShackTime = GM_getValue("userSettingFixShackTime", false);
		setDateElems(getDateElems());
	}
	
	function xpath(query) {
		return document.evaluate(query, document, null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	}
	
	function getDateElems() {
		var allElems = new Array();
		var items;
		if (window.location.pathname == '/msgcenter/' || window.location.pathname == '/search.x') {
			items = xpath("//td[contains(@class, 'date')]");
		} else {
			items = xpath("//span[contains(@class, 'date')] | //div[contains(@class, 'postdate')]");
		}
		for (item = null, i = 0; item = items.snapshotItem(i); i++) {
			allElems.push(item);
		}
		return allElems; 
	}
	
	function setDateElems(elems) {
		if (window.location.pathname == '/search.x') {
			for (var i = 0; i < elems.length; i++) {
				var tempDate = getSingleDateSearch(elems[i]);
				tempDate = getLocalDate(tempDate);
				tempDate = getDateFormat(tempDate);
				elems[i].innerHTML = tempDate;
			}
		} else {
			for (var i = 0; i < elems.length; i++) {
				var tempDate = getSingleDate(elems[i]);
				tempDate = getLocalDate(tempDate);
				tempDate = getDateFormat(tempDate);
				elems[i].innerHTML = tempDate;
			}
		}
	}
	
	function getSingleDate(elem) {
		var tempDate = elem.innerHTML;
		tempDate = tempDate.replace(dateRegex, "$1,$2,$3,$4,$5,$6,$7,$8");
		tempDate = tempDate.split(",");
		var month = monthArray.indexOf(tempDate[01]);
		var day = parseInt(tempDate[2], 10);
		var year = parseInt(tempDate[3], 10);
		var hour = parseInt(tempDate[4], 10);
		var minute = parseInt(tempDate[5], 10);
		var meridian = tempDate[6];
		var timezone = tempDate[7];
		if((meridian == 'pm') && (hour < 12)) {
			hour+=12;
		}
		if((meridian == 'am') && (hour == 12)) {
			hour = 0;
		}
		var utcDate = new Date(year,month,day,hour,minute,0,0);
		return utcDate;
	}

	function getSingleDateSearch(elem) {
		var tempDate = elem.innerHTML;
		tempDate = tempDate.replace(dateRegexSearch, "$1,$2,$3,$4,$5,$6");
		tempDate = tempDate.split(",");
		var month = monthArray.indexOf(tempDate[2]);
		var day = parseInt(tempDate[1], 10);
		var year = parseInt(tempDate[3], 10);
		var hour = parseInt(tempDate[4], 10);
		var minute = parseInt(tempDate[5], 10);
		var utcDate = new Date(year,month,day,hour,minute,0,0);
		return utcDate;
	}
	
	function getLocalDate(utcDate) {
		utcDate.setSeconds(timeZoneOffset);
		return utcDate;
	}
	
	function getDateFormat(utcDate) {
		var month = monthArray[utcDate.getMonth()];
		var day = utcDate.getDate();
		var year = utcDate.getFullYear();
		var hour = utcDate.getHours();
		var minute = utcDate.getMinutes();
		if(minute < 10) minute = '0'+minute;
		if (userSetting24Hr == "true") {
			if (hour < 10) hour = '0'+hour;
			return (month+' '+day+', '+year+' '+hour+':'+minute+' '+(userSettingHideAbbr=="true"?'':timeZoneAbbr));
		} else {
			var meridian = 'am';
			if(hour >= 12) meridian = 'pm';
			if(hour > 12) hour -= 12;
			if(hour == 0) {
				hour = 12;
				meridian = 'am';
			}
			return (month+' '+day+', '+year+' '+hour+':'+minute+''+meridian+' '+(userSettingHideAbbr=="true"?'':timeZoneAbbr));
		}
	}
	
	//Control Panel Functions
	
	function settingsFactory() {
		getControlPanel();
		getUserSettings();
	}
	
	function getControlPanel() {
		var accForm = document.getElementById('shackscripts_options');
        if (accForm) 
		  {
            var timeZoneDiv = document.createElement('div');
            accForm.parentNode.insertBefore(timeZoneDiv, accForm.nextSibling);
            timeZoneDiv.innerHTML = '<h5>Timezone Settings</h5>' +
            '<p>All timestamps displayed on Shacknews can be automatically corrected to show the correct time for your location in the world. Simply select the appropriate time zone from the list below.</p>' +
            '<label for=\"timeZoneSetting\">Timezone:</label>' +
            '<select id=\"timeZoneSetting\" style="max-width: none ! important;">' +
            getTimeZoneList() +
            '</select><br /><br />' +
            'In addition you may set the appropiate options for Daylight Saving Time:<br />' +
            '<label for=\"DSTSetting\"><input type=\"checkbox\" id=\"DSTSetting\" checked=\"true\" />Adjust for Daylight Saving.</label>' +
            '<label for=\"shackDST\"><input type=\"checkbox\" id=\"shackDST\" checked=\"true\" />Shack is running Daylight Saving. ' +
            'The Shack also maybe running on Daylight Saving Time, change this setting to compensate.</label>' +
            '<br />Display Options:<br />' +
            '<label for=\"hideAbbr\"><input type=\"checkbox\" id=\"hideAbbr\" checked=\"false\" />' +
            'Hide time zone abbreviation (e.g.: EST, PST, CST, etc.)</label>' +
            '<label for=\"set24Hr\"><input type=\"checkbox\" id=\"set24Hr\" checked=\"false\" />Use 24-hour clock.</label>' +
            '<br />' +
            '<label for=\"fixShackTime\"><input type=\"checkbox\" id=\"fixShackTime\" checked=\"false\" />Fix Shack time. ' +
            'Time on Shack server seems to be -3 minutes off or so.</label>' +
            '<div class=\"control submit\"><button type=\"submit\" id=\"timeZoneButton\">Update TimeZone</button></div>';
            document.getElementById('timeZoneButton').addEventListener('click', setUserSettings, true);
        }
	}
	
	function getTimeZoneList() {
		var timeZoneOptions = '';
		for (var i=0; i < timeZones.length; i++) {
			timeZoneOptions += '<option value=\"'+i+'\">'
			+ timeZones[i].desc
			+ '</option>';
		}
		return timeZoneOptions;
	}

	function getUserSettings() {
		if(GM_getValue("userSettingDST") == "true") {
			document.getElementById('DSTSetting').checked = true;
		} else {
			document.getElementById('DSTSetting').checked = false;
		}
		
		if(GM_getValue("shackDST") == "true") {
			document.getElementById('shackDST').checked = true;
		} else {
			document.getElementById('shackDST').checked = false;
		}
		
		if(GM_getValue("userSettingHideAbbr") == "true") {
			document.getElementById('hideAbbr').checked = true;
		} else {
			document.getElementById('hideAbbr').checked = false;
		}

		if(GM_getValue("userSetting24Hr") == "true") {
			document.getElementById('set24Hr').checked = true;
		} else {
			document.getElementById('set24Hr').checked = false;
		}

		if(GM_getValue("userSettingFixShackTime") == "true") {
			document.getElementById('fixShackTime').checked = true;
		} else {
			document.getElementById('fixShackTime').checked = false;
		}
        
        if(GM_getValue("userSettingTimeZone")) {
			document.getElementById('timeZoneSetting').options[GM_getValue("userSettingTimeZone")].selected = true;
		} else {
			document.getElementById('timeZoneSetting').options[13].selected = true;
		}
	}
	
	function setUserSettings(event) 
	{
		var id = document.getElementById('timeZoneSetting').value;
		var DSTSetting = document.getElementById('DSTSetting').checked;
		var shackDST = document.getElementById('shackDST').checked;
		var hideAbbr = document.getElementById('hideAbbr').checked;
		var set24Hr = document.getElementById('set24Hr').checked;
		var fixShackTime = document.getElementById('fixShackTime').checked;
		var timeZoneOffSet = (timeZones[id].offset * 3600);
		timeZoneOffSet += 21600;	// I don't understand this line, plzhlp --dodob
		if(shackDST) { timeZoneOffSet -= 3600;}
		if(DSTSetting) { timeZoneOffSet += 3600;}
		if(fixShackTime) { timeZoneOffSet += 180;}	// -3 minute offset on shack servers
		GM_setValue("userSettingTimeZone", id);
		GM_setValue("userSettingDST", DSTSetting);
		GM_setValue("shackDST", shackDST);
		GM_setValue("timeZoneOffset", timeZoneOffSet);
		GM_setValue("timeZoneAbbr", timeZones[id].abbr);
		GM_setValue("userSettingHideAbbr", hideAbbr);
		GM_setValue("userSetting24Hr", set24Hr);
		GM_setValue("userSettingFixShackTime", fixShackTime);
		alert('Timezone Updated.');
		event.stopPropagation();
		event.preventDefault();
	}
	
	factory();
	if (GM_log) { GM_log('Shacktimezone: ' + (getTime() - scriptStartTime) + 'ms'); }
}

